<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>项目生成器</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="layui/css/layui.css"/>
    <link rel="stylesheet" href="module/all.css"/>
</head>
<body>
<div class="layui-container">
    <div class="layui-row layui-col-space20">
        <div class="layui-col-md4">
            <div class="layui-card">
                <div class="layui-card-header">生成记录</div>
                <div class="layui-card-body gen-history-list" style="height: 375px;">
                    <div class="gen-empty-view">
                        <i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>
                        <p>加载中...</p>
                    </div>
                </div>
            </div>
            <div class="layui-card" style="margin-top: 20px;">
                <div class="layui-card-header">模板列表</div>
                <div class="layui-card-body" style="padding-top: 0;padding-bottom: 15px;">
                    <div class="gen-tpl-list" style="height: 120px;">
                        <div class="gen-empty-view">
                            <i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>
                            <p>加载中...</p>
                        </div>
                    </div>
                    <button id="btnUploadTpl" class="layui-btn layui-btn-fluid layui-btn-primary">
                        <i class="layui-icon">&#xe681;</i><span>上传模板</span>
                    </button>
                </div>
            </div>
        </div>
        <div class="layui-col-md8">
            <div class="layui-card">
                <div class="layui-card-header">项目生成</div>
                <div class="layui-card-body" style="padding-top: 20px;">
                    <div class="layui-tab layui-steps layui-steps-readonly" lay-filter="generatorTab"
                         style="visibility: hidden;">
                        <ul class="layui-tab-title">
                            <li class="layui-this">
                                <i class="layui-icon layui-icon-ok">1</i>
                                <span class="layui-steps-title">第一步</span>
                                <span class="layui-steps-content">数据库连接配置</span>
                            </li>
                            <li>
                                <i class="layui-icon layui-icon-ok">2</i>
                                <span class="layui-steps-title">第二步</span>
                                <span class="layui-steps-content">业务模块划分</span>
                            </li>
                            <li>
                                <i class="layui-icon layui-icon-ok">3</i>
                                <span class="layui-steps-title">第三步</span>
                                <span class="layui-steps-content">项目信息配置</span>
                            </li>
                        </ul>
                        <div class="layui-tab-content">
                            <!-- 第一步 -->
                            <div class="layui-tab-item layui-form layui-show" lay-filter="generatorFrom1">
                                <div class="gen-from-body">
                                    <div class="layui-form-item" style="margin-top: 50px;">
                                        <label class="layui-form-label layui-form-required">连接地址:</label>
                                        <div class="layui-input-block">
                                            <input name="url" class="layui-input" placeholder="请输入数据库连接地址"
                                                   value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8"
                                                   lay-verify="required" required/>
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">连接账号:</label>
                                        <div class="layui-input-block">
                                            <input name="username" value="root" class="layui-input"
                                                   placeholder="请输入数据库连接账号"/>
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">连接密码:</label>
                                        <div class="layui-input-block">
                                            <input name="password" value="123456" class="layui-input"
                                                   placeholder="请输入数据库连接密码" lay-verify="required" required/>
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">连接驱动:</label>
                                        <div class="layui-input-block">
                                            <input name="driverName" value="com.mysql.cj.jdbc.Driver"
                                                   placeholder="请输入数据库连接驱动名"
                                                   class="layui-input" lay-verify="required" required/>
                                        </div>
                                    </div>
                                </div>
                                <div class="layui-form-item">
                                    <button id="btnGoLast" class="layui-btn layui-btn-primary">最后一步</button>&emsp;
                                    <button class="layui-btn" lay-filter="generatorSubmit1" lay-submit>下一步</button>
                                </div>
                            </div>
                            <!-- 第二步 -->
                            <div class="layui-tab-item layui-form" lay-filter="generatorFrom2">
                                <div class="gen-from-body">
                                    <div class="layui-form-item" style="margin-top: 25px;">
                                        <button id="btnAddModel" class="layui-btn layui-btn-fluid layui-btn-primary">
                                            <i class="layui-icon">&#xe624;</i>增加模块
                                        </button>
                                    </div>
                                </div>
                                <div class="layui-form-item">
                                    <button data-steps="prev" class="layui-btn layui-btn-primary">上一步</button>&emsp;
                                    <button class="layui-btn" lay-filter="generatorSubmit2" lay-submit>下一步</button>
                                </div>
                            </div>
                            <!-- 第三步 -->
                            <div class="layui-tab-item layui-form" lay-filter="generatorFrom3">
                                <div class="gen-from-body">
                                    <div class="gen-form-header"><span>项目信息</span></div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">项目名称:</label>
                                        <div class="layui-input-block">
                                            <input name="projectName" class="layui-input" placeholder="例如: javabb-cms"
                                                   lay-verify="required" required/>
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">Group Id:</label>
                                        <div class="layui-input-block">
                                            <input name="groupId" class="layui-input" placeholder="例如: cn.javabb"
                                                   value="cn.javabb" lay-verify="required" required/>
                                            <div class="layui-form-mid layui-word-aux">GroupId建议统一为公司域名</div>
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">项目包名:</label>
                                        <div class="layui-input-block">
                                            <div class="layui-input-wrapper">
                                                <div class="layui-input-prefix"></div>
                                                <input name="packageName" class="layui-input" placeholder="例如: cms"
                                                       lay-verify="required" required/>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="gen-form-header"><span>其它配置</span></div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">作者名称:</label>
                                        <div class="layui-input-block">
                                            <input name="author" class="layui-input" placeholder="请输入作者名称"
                                                   value="Javabb" lay-verify="required" required/>
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">框架模板:</label>
                                        <div class="layui-input-block">
                                            <select name="tplName" lay-verify="required" required>
                                                <option value="">请选择框架模板</option>
                                            </select>
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">权限注解:</label>
                                        <div class="layui-input-block">
                                            <input type="radio" name="needPerm" value="true" title="需要" checked/>
                                            <input type="radio" name="needPerm" value="false" title="不需要"/>
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">日志注解:</label>
                                        <div class="layui-input-block">
                                            <input type="radio" name="needLog" value="true" title="需要" checked>
                                            <input type="radio" name="needLog" value="false" title="不需要"/>
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <label class="layui-form-label layui-form-required">菜单起始ID:</label>
                                        <div class="layui-input-block">
                                            <input name="menuStartId" class="layui-input" placeholder="请输入菜单起始ID"
                                                   type="number" value="37" lay-verify="required|number" required/>
                                            <div class="layui-form-mid layui-word-aux">用于生成菜单表的sql语句</div>
                                        </div>
                                    </div>
                                </div>
                                <div class="layui-form-item">
                                    <button data-steps="prev" class="layui-btn layui-btn-primary">上一步</button>&emsp;
                                    <button class="layui-btn" lay-filter="generatorSubmit3" lay-submit>立即生成</button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- 模块划分item渲染模板 -->
<script type="text/html" id="tplStep2Item">
    <div class="gen-from-body model-item" data-index="{{d.modelIndex}}">
        <div class="gen-form-header"><span>业务模块</span></div>
        <div class="dropdown-menu">
            <i class="layui-icon">&#x1006;</i>
            <div class="dropdown-menu-nav dropdown-popconfirm dropdown-bottom-right">
                <div class="dropdown-anchor"></div>
                <div class="dropdown-popconfirm-title">
                    <i class="layui-icon layui-icon-help"></i>
                    确定要删除此模块吗？
                </div>
                <div class="dropdown-popconfirm-btn">
                    <button class="layui-btn" btn-cancel>取消</button>
                    <button ew-event="closeCard" class="layui-btn">确定</button>
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">模块名:</label>
            <div class="layui-input-block">
                <input name="model_{{d.modelIndex}}" class="layui-input" placeholder="例如: system"/>
                <div class="layui-form-mid layui-word-aux">可为空,以字母命名,不要以数字开头</div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">模块的表:</label>
            <div class="layui-input-block" id="table_{{d.modelIndex}}"></div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">表前缀:</label>
            <div class="layui-input-block">
                <input name="table_prefix_{{d.modelIndex}}" class="layui-input" placeholder="例如: sys_"/>
            </div>
        </div>
    </div>
</script>
<!-- js部分 -->
<script type="text/javascript" src="layui/layui.js"></script>
<script>
    layui.config({base: 'module/'}).use(['form', 'xmSelect', 'laytpl', 'steps', 'dropdown', 'util', 'upload'], function () {
        var $ = layui.jquery;
        var layer = layui.layer;
        var form = layui.form;
        var xmSelect = layui.xmSelect;
        var laytpl = layui.laytpl;
        var steps = layui.steps;
        var util = layui.util;
        var upload = layui.upload;
        var tableInfos = [];   // 表信息
        var tbSelIns = [];  // 多选下拉实例
        var formData1 = {}, formData2 = {};  // 表单数据
        var isGoLast = false;  // 是否跳转到最后一步
        $('[lay-filter="generatorTab"]').css('visibility', 'visible');

        /* 获取模板列表 */
        function getTplList() {
            var $list = $('.gen-tpl-list');
            changeEmptyView($list.children('.gen-empty-view'), '加载中...', 0);
            $.get('api/generator/templates', function (res) {
                if (0 === res.code) {
                    var $sel = $('[lay-filter="generatorFrom3"] select[name="tplName"]');
                    if (res.data.length === 0) {
                        changeEmptyView($list.children('.gen-empty-view'), '无数据', 1);
                        $sel.html('<option value="">请选择框架模板</option>');
                    } else {
                        $list.html('');
                        $sel.html('');
                        res.data.forEach(function (item) {
                            $sel.append('<option value="' + item.name + '">' + item.name + '</option>');
                            var html = '<div class="tpl-list-item">';
                            html += '      <i class="layui-icon">&#xe628;</i><span class="title">' + item.name + '</span>';
                            html += '      <span class="time">' + item.size / 1000 + 'kb</span>';
                            html += '   </div>';
                            $list.append(html);
                        });
                        form.render('select', 'generatorFrom3');
                    }
                } else {
                    changeEmptyView($list.children('.gen-empty-view'), res.msg, 2);
                }
            });
        }

        getTplList();

        /* 获取生成记录 */
        function getHistoryList() {
            var $list = $('.gen-history-list');
            changeEmptyView($list.children('.gen-empty-view'), '加载中...', 0);
            $.get('api/generator/history', function (res) {
                if (0 === res.code) {
                    if (res.data.length === 0) {
                        changeEmptyView($list.children('.gen-empty-view'), '没有生成记录', 1);
                    } else {
                        $list.html('');
                        res.data.forEach(function (item) {
                            var html = '<div class="history-list-item">';
                            html += '      <i class="layui-icon">&#xe60a;</i><span class="title">' + item.name + '</span>';
                            html += '      <span class="time">' + util.toDateString(item.updateTime) + '</span>';
                            html += '      <a target="_blank" href="api/generator/download?file=' + item.id + '/' + item.name + '.zip">下载</a>';
                            html += '   </div>';
                            $list.append(html);
                        });
                    }
                } else {
                    changeEmptyView($list.children('.gen-empty-view'), res.msg, 2);
                }
            });
        }

        getHistoryList();

        /* 切换空视图状态 */
        function changeEmptyView(view, text, type) {
            var $empty = $(view);
            $empty.children('p').text(text);
            if (type === 0) {  // 加载中
                $empty.children('.layui-icon').addClass('layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
                $empty.children('.layui-icon').removeClass('layui-icon-face-cry layui-icon-face-surprised');
            } else if (type === 1) {  // 空数据
                $empty.children('.layui-icon').removeClass('layui-icon-face-cry layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
                $empty.children('.layui-icon').addClass('layui-icon-face-surprised');
            } else {  // 错误
                $empty.children('.layui-icon').removeClass('layui-icon-face-surprised layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
                $empty.children('.layui-icon').addClass('layui-icon-face-cry');
            }
        }

        /* ------------------第一步------------------- */

        // 获取表信息
        form.on('submit(generatorSubmit1)', function (data) {
            formData1 = data.field;
            if (!isGoLast) {
                var loadIndex = layer.msg('获取数据表信息...', {icon: 16, shade: 0.01, time: false});
                $.ajax({
                    url: 'api/generator/tables',
                    data: data.field,
                    method: 'get',
                    dataType: 'json',
                    success: function (res) {
                        layer.close(loadIndex);
                        if (res.code === 0) {
                            tableInfos = res.data || [];
                            initStep2();
                            steps.next('generatorTab');
                        } else {
                            layer.msg(res.msg || '无法连接数据库', {icon: 2, anim: 6});
                        }
                    },
                    error: function (xhr) {
                        layer.close(loadIndex);
                        layer.msg(xhr.status + ': ' + xhr.statusText, {icon: 2, anim: 6});
                    }
                });
            } else {
                isGoLast = false;
                formData2 = {};
                steps.go('generatorTab', 2);
            }
            return false;
        });

        // 最后一步
        $('#btnGoLast').click(function () {
            isGoLast = true;
            $('[lay-filter="generatorSubmit1"]').trigger('click');
        });

        // 初始化第二步
        function initStep2() {
            $('#btnAddModel').parent().prevAll().remove();
            tbSelIns = [];
            formData2 = {};
            addModel(1);
        }

        /* ------------------第二步------------------- */

        // 添加模块
        function addModel(index) {
            if (tableInfos.length <= 0) return;
            laytpl(tplStep2Item.innerHTML).render({
                modelIndex: index
            }, function (html) {
                $('#btnAddModel').parent().before(html);
                var dataList = [];
                for (var i = 0; i < tableInfos.length; i++) {
                    dataList.push({
                        name: tableInfos[i].name + '（' + tableInfos[i].comment + '）',
                        value: tableInfos[i].name
                    });
                }
                var ins = xmSelect.render({
                    el: '#table_' + index,
                    height: '300px',
                    autoRow: false,
                    data: dataList,
                    toolbar: {show: true},
                    theme: {color: '#5FB878'},
                    on: function (data) {
                        var $input = $('input[name="table_prefix_' + index + '"]');
                        var prefix = [];
                        $.each(data.arr, function (index, item) {
                            var pre = item.value.substring(0, item.value.indexOf('_') + 1);
                            (prefix.indexOf(pre) === -1) && prefix.push(pre);
                        });
                        $input.val(prefix.join(','));
                    },
                    show: function () {
                        $('#table_' + index + '>xm-select').addClass('xm-select-opened');
                    },
                    hide: function () {
                        $('#table_' + index + '>xm-select').removeClass('xm-select-opened');
                    }
                });
                tbSelIns.push(ins);
            });
        }

        // 增加模块按钮点击事件
        $('#btnAddModel').click(function () {
            if (tableInfos.length > 0) {
                var index = $(this).parent().parent().children('.model-item').length + 1;
                addModel(index);
            } else {
                layer.msg('没有数据表', {icon: 2, anim: 6});
            }
        });

        // 删除模块
        $(document).on('click', '[ew-event="closeCard"]', function () {
            var $card = $(this).parent().parent().parent().parent();
            tbSelIns[parseInt($card.data('index')) - 1] = undefined;
            $card.html('');
            $card.hide();
        });

        // 模块配置表单提交
        form.on('submit(generatorSubmit2)', function (data) {
            formData2 = data.field;
            // 验证
            var lastModelName = undefined;
            for (var f in formData2) {
                if (!formData2.hasOwnProperty(f)) continue;
                if (f.indexOf('model_') === 0) {
                    if (formData2[f] === 'common') {
                        layer.msg('模块名不能为common', {icon: 2, anim: 6});
                        return false;
                    }
                    if (lastModelName === undefined) {
                        lastModelName = formData2[f];
                    } else if (lastModelName === formData2[f]) {
                        layer.msg('多个模块名不能相同', {icon: 2, anim: 6});
                        return false;
                    }
                }
            }
            steps.next('generatorTab');
            return false;
        });

        /* ------------------第三步------------------- */

        // 项目配置表单提交
        form.on('submit(generatorSubmit3)', function (data) {
            if (data.field.packageName === 'common') {
                return layer.msg('包名不能为common', {icon: 2, anim: 6});
            }
            var config = $.extend({}, formData1);
            config = $.extend(config, formData2);
            config = $.extend(config, data.field);
            config.models = [];
            for (var i = 0; i < tbSelIns.length; i++) {
                if (tbSelIns[i]) {
                    config.models.push({
                        modelName: config['model_' + (i + 1)],
                        tables: tbSelIns[i].getValue('value'),
                        prefix: config['table_prefix_' + (i + 1)].split(',')
                    });
                }
            }
            config.packageName = config.groupId + '.' + config.packageName;
            // 校验表选择是否有重复
            for (var j = 0; j < config.models.length; j++) {
                var tempModelName = config.models[j].modelName;
                for (var k = 0; k < config.models[j].tables.length; k++) {
                    var tempTbName = config.models[j].tables[k];
                    for (var m = 0; m < config.models.length; m++) {
                        if (config.models[m].modelName !== tempModelName) {
                            for (var n = 0; n < config.models[m].tables.length; n++) {
                                var tempTbName2 = config.models[m].tables[n];
                                if (tempTbName2 === tempTbName) {
                                    layer.msg('多个模块选择的表有重复', {icon: 2, anim: 6});
                                    steps.prev('generatorTab');
                                    return false;
                                }
                            }
                        }
                    }
                }
            }
            //
            var loadIndex = layer.msg('正在生成中，请稍后...', {icon: 16, shade: 0.01, time: false});
            $.ajax({
                url: 'api/generator',
                data: JSON.stringify(config),
                method: 'post',
                dataType: 'json',
                contentType: "application/json;charset=utf-8",
                success: function (res) {
                    layer.close(loadIndex);
                    if (0 === res.code) {
                        layer.msg('项目生成完毕，即将开始下载...', {icon: 1});
                        var $iframe = $('#downloadIframe');
                        if ($iframe.length === 0) {
                            $('body').append('<iframe id="downloadIframe" style="display: none;"></iframe>');
                            $iframe = $('#downloadIframe');
                        }
                        $iframe.attr('src', 'api/generator/download?file=' + res.data);
                        getHistoryList();
                    } else {
                        layer.alert(res.msg || '生成失败，请检查配置~', {title: '生成失败', icon: 2, shade: 0.01});
                    }
                },
                error: function (xhr) {
                    layer.close(loadIndex);
                    layer.msg(xhr.status + ': ' + xhr.statusText, {icon: 2, anim: 6});
                }
            });
            return false;
        });

        // groupId改变事件
        var $packagePrefix = $('input[name="packageName"]').prev();
        var $groupId = $('input[name="groupId"]');
        $groupId.on('input', function () {
            $packagePrefix.text($(this).val() + ".");
        });
        $packagePrefix.text($groupId.val() + ".");

        /* 上传模板 */
        upload.render({
            elem: '#btnUploadTpl',
            url: 'api/generator/upload',
            accept: 'file',
            exts: 'zip',
            before: function (obj) {
                layer.msg('正在上传中，请稍后...', {icon: 16, shade: 0.01, time: false});
            },
            done: function (res) {
                layer.closeAll('loading');
                if (0 === res.code) {
                    layer.msg(res.msg, {icon: 1});
                    getTplList();
                } else {
                    layer.msg(res.msg, {icon: 2, anim: 6});
                }
            },
            error: function () {
                layer.closeAll('loading');
                layer.msg('上传失败', {icon: 2, anim: 6});
            }
        });

    });
</script>
</body>
</html>